<?php

namespace App\Modules\Health\Http\Controllers\Api;

use App\Constants\HealthNoteConstant;
use App\Exceptions\BusinessException;
use App\Http\Controllers\Api\Controller;
use App\Models\HealthNote;
use App\Models\HealthNoteComments;
use App\Models\HealthNoteFavorites;
use App\Modules\Health\Models\Meridian;
use Illuminate\Contracts\Cache\LockTimeoutException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class MeridianController extends Controller
{
    public function info(int $id)
    {
        $info = Meridian::find($id);

        if (!$info || !$info->status) return $this->error('信息不存在');

        $memberId = auth('api')->user()->id ?? 0;

        $info->load([
            'acu'  => function ($q) {
                return $q->select(['id', 'name']);
            },
            'note' => function ($q) use ($memberId) {
                return $q
                    ->with('member:id,nickname,avatar')
                    ->with('pusher:id,name,avatar')
                    ->withCount(['favorites as self_fav' => function ($q) use ($memberId) {
                        return $q->where('member_id', $memberId)->where('comment_id', 0);
                    }])
                    ->withCount(['comments' => function ($q) {
                        return $q->where('examine_status', HealthNoteConstant::SUC_EXAMINE)->where('is_show', 1);
                    }])
                    ->when($memberId, function ($q) use ($memberId) {
                        $q->whereRaw('IF(member_id = ?, examine_status <> ?, examine_status = ? AND is_show = 1)', [$memberId, HealthNoteConstant::FAIL_EXAMINE, HealthNoteConstant::SUC_EXAMINE]);
                    }, function ($q) {
                        $q->where('examine_status', HealthNoteConstant::SUC_EXAMINE)->where('is_show', 1);
                    })
                    ->orderByDesc('is_hot')
                    ->orderByDesc('id')
                    ->limit(10);
            }
        ]);


        return $this->_success(compact('info'));
    }

    public function store(Request $request)
    {
        $memberId = auth('api')->user()->id ?? 0;
        if (!$memberId) return $this->error('请先登录', [], 40001, 401);

        $data = Validator::make($request->post(), [
            'id'      => 'required',
            'title'   => 'required',
            'content' => 'required',
        ], [
            'id.required'      => '经脉ID不能为空',
            'title.required'   => '标题不能为空',
            'content.required' => '内容不能为空',
        ])->validate();

        $info = Meridian::find($data['id']);
        if (!$info) return $this->error('信息不存在');

        HealthNote::create([
            'title'       => $data['title'],
            'content'     => $data['content'],
            'member_id'   => $memberId,
            'belong_type' => HealthNoteConstant::TYPE_bY_MERIDIAN,
            'belong_id'   => $data['id'],
        ]);

        return $this->success('操作成功');
    }

    public function favNote(int $id)
    {
        $lock = Cache::lock('FAV_NOTE_' . $id, 10);

        try {
            $lock->block(5);

            DB::beginTransaction();

            $memberId = auth('api')->user()->id ?? 0;
            if (!$memberId) throw new BusinessException('未登录', 40001);

            $note = HealthNote::find($id);
            if (!$note) throw new BusinessException('信息不存在');

            $fav = HealthNoteFavorites::where([
                'member_id'  => $memberId,
                'note_id'    => $id,
                'comment_id' => 0,
            ])->first();

            if ($fav) {
                $fav->delete();
                if ($note->fav_count > 0) {
                    $note->decrement('fav_count');
                }
            } else {
                HealthNoteFavorites::create([
                    'member_id'  => $memberId,
                    'note_id'    => $id,
                    'comment_id' => 0,
                ]);

                $note->increment('fav_count');
            }

            DB::commit();
        } catch (LockTimeoutException $le) {
            return $this->error('操作频繁,请稍后再试');
        } catch (\Throwable $e) {
            DB::rollBack();
            if (is_a($e, BusinessException::class)) throw $e;

            log_exception('点赞经脉日记操作失败', $e);
            return $this->error('操作失败');
        } finally {
            optional($lock)->release();
        }

        return $this->success('操作成功');
    }

    public function noteRely(int $id)
    {
        $lock = Cache::lock('RELY_NOTE_' . $id, 10);

        try {
            $lock->block(5);

            DB::beginTransaction();

            $note = HealthNote::find($id);
            if (!$note) throw new BusinessException('信息不存在');

            $note->increment('relay_count');

            DB::commit();
        } catch (LockTimeoutException $le) {
            return $this->error('操作频繁,请稍后再试');
        } catch (\Throwable $e) {
            if (is_a($e, BusinessException::class)) throw $e;

            log_exception('转发经脉日记操作失败', $e);
            return $this->error('操作失败');
        } finally {
            optional($lock)->release();
        }

        return $this->success('操作成功');
    }

    public function noteInfo(int $id)
    {
        $info = HealthNote::find($id);
        if (!$info) return $this->error('信息不存在');

        $memberId = auth('api')->user()->id ?? 0;

        $info->load([
            'belong',
            'comments' => function ($q) use ($memberId) {
                $q->select(['id', 'note_id', 'pusher_id', 'fav_count', 'content', 'created_at', DB::raw('0 as self_fav')])
                    ->with('member:id,nickname,avatar')
                    ->when($memberId, function ($q) use ($memberId) {
                        $q->whereRaw('IF(pusher_id = ?, examine_status <> ?, examine_status = ? AND is_show = 1)', [$memberId, HealthNoteConstant::FAIL_EXAMINE, HealthNoteConstant::SUC_EXAMINE]);
                    }, function ($q) {
                        $q->where('examine_status', HealthNoteConstant::SUC_EXAMINE)->where('is_show', 1);
                    })
                    ->orderByDesc('id');
            },
            'member:id,nickname,avatar',
            'pusher:id,name,avatar',
        ]);

        if ($memberId) {
            $info->self_fav = HealthNoteFavorites::where([
                'member_id' => $memberId,
                'note_id'   => $id,
            ])->exists() ? 1 : 0;

            $commentIds = HealthNoteFavorites::where('member_id', $memberId)
                ->where('note_id', $id)
                ->where('comment_id', '>', 0)
                ->pluck('comment_id')
                ->all();

            foreach ($info->comments as $comment) {
                $comment->self_fav = in_array($comment->id, $commentIds) ? 1 : 0;
            }
        } else {
            $info->self_fav = 0;
        }

        return $this->_success(compact('info'));
    }

    public function comment(Request $request)
    {
        $memberId = auth('api')->user()->id ?? 0;
        if (!$memberId) return $this->error('请先登录', [], 40001, 401);

        $data = Validator::make($request->post(), [
            'id'      => 'required',
            'content' => 'required',
        ], [
            'id.required'      => '经脉ID不能为空',
            'content.required' => '内容不能为空',
        ])->validate();

        $info = HealthNote::find($data['id']);
        if (!$info) return $this->error('信息不存在');

        HealthNoteComments::create([
            'note_id'   => $info->id,
            'pusher_id' => $memberId,
            'content'   => $data['content'],
        ]);

        return $this->success('操作成功');
    }

    public function favNoteComment(int $id)
    {
        $lock = Cache::lock('FAV_NOTE_COMMENT_' . $id, 10);

        try {
            $lock->block(5);

            DB::beginTransaction();

            $memberId = auth('api')->user()->id ?? 0;
            if (!$memberId) throw new BusinessException('未登录', 40001);

            $info = HealthNoteComments::find($id);
            if (!$info) throw new BusinessException('信息不存在');

            $fav = HealthNoteFavorites::where([
                'member_id'  => $memberId,
                'note_id'    => $info->note_id,
                'comment_id' => $id,
            ])->first();

            if ($fav) {
                $fav->delete();
                if ($info->fav_count > 0) {
                    $info->decrement('fav_count');
                }
            } else {
                HealthNoteFavorites::create([
                    'member_id'  => $memberId,
                    'note_id'    => $info->note_id,
                    'comment_id' => $id,
                ]);

                $info->increment('fav_count');
            }

            DB::commit();
        } catch (LockTimeoutException $le) {
            return $this->error('操作频繁,请稍后再试');
        } catch (\Throwable $e) {
            DB::rollBack();
            if (is_a($e, BusinessException::class)) throw $e;

            log_exception('点赞日记评论操作失败', $e);
            return $this->error('操作失败');
        } finally {
            optional($lock)->release();
        }

        return $this->success('操作成功');
    }
}
